home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Tools
/
awf
/
pass1
< prev
next >
Wrap
Text File
|
1995-05-16
|
9KB
|
213 lines
# first pass: macro expansion and .if
# We support macros, conditionals (of three quite limited forms), and macro
# argument substitution.
BEGIN {
curmacro = ""
macros[""] = 0 # just to make it an array
macrolen[""] = 0 # just to make it an array
macrotext[0] = "" # just to make it an array
args[""] = "" # just to make it an array
ntext = 1 # first slot in macrotext; cannot be 0
nroffset = 0 # offset between NR and "real" line numbers
inname = "?" # input filename
sp = 0 # stack "pointer" (number of stacked macros)
maxsp = 25 # limit on nesting depth
macrostack[sp] = "" # to make it an array
nleftstack[sp] = "" # to make it an array
ptrstack[sp] = "" # to make it an array
nargstack[sp] = "" # to make it an array
argstack[sp] = "" # to make it an array
condstack[sp] = "" # to make it an array
}
/^\.\^#/ { # filename and line no of next line: .^# no fn
nroffset = (NR+1) - $2
inname = $3
print
next
}
/^\.de/ { # macro start
curmacro = "." $2
macros[curmacro] = ntext
macrostart = ntext
next
}
curmacro != "" && $0 !~ /^\.\.$/ { # macro text - \\ becomes \
if ($0 !~ /\\/) # quick case, no backslashes
line = $0
else {
line = ""
for (n = 1; n <= length; n++) {
if (substr($0, n, 2) == "\\\\")
n++
line = line substr($0, n, 1)
}
}
macrotext[ntext++] = line
next
}
curmacro != "" && $0 ~ /^\.\.$/ { # macro end
macrolen[curmacro] = ntext - macrostart
curmacro = ""
print ".^#", NR - nroffset + 1, inname
next
}
$0 ~ /^\./ && ( macros[$1] != 0 || $0 ~ /^\.(i[ef]|el)/ ) {
# something that needs attention
print ".^=", NR - nroffset, inname
line = $0
nleft = 0
macro = "<none>"
nargs = 0
while (line != "") {
# conditionals; note that 1-n is !n (awk doesn't have !)
invert = 0
if (line ~ /^\.i[ef] !/)
invert = 1
prevcond = cond
cond = 0
if (line !~ /^\.(i[ef]|el)/) { # not conditional
cond = 1
iflen = 0
} else if (line ~ /^\.i[ef] !?\\n\(\.\$[<=>][0-9] /) {
# arithmetic comparison on arg count
iflen = length(".if .n(.$=x ") + invert
n = substr(line, iflen-1, 1) + 0
op = substr(line, iflen-2, 1)
if (op == "=" && nargs == n)
cond = 1
else if (op == "<" && nargs < n)
cond = 1
else if (op == ">" && nargs > n)
cond = 1
} else if (line ~ /^\.i[ef] !?'\\\$[0-9]'[^']*' /) {
# string equality on argument
iflen = length(".if '.$n'") + invert
n = substr(line, iflen-1, 1)+0
if (n <= nargs)
s1 = args[n]
else
s1 = ""
i = index(substr(line, iflen+1), "'")
s2 = substr(line, iflen+1, i-1)
iflen += i+1
if (s1 == s2)
cond = 1
} else if (line ~ /^\.i[ef] !?[nt] /) {
# nroff vs troff
iflen = length(".if n ") + invert
if (substr(line, iflen-1, 1) == "n")
cond = 1
} else if (line ~ /^\.el /) {
cond = 1 - prevcond
iflen = length(".el ")
} else {
line = ".tm unknown .if/.ie form: " line
cond = 1
iflen = 0
}
if (invert)
cond = 1 - cond
if (cond && iflen > 0) # trim true conditional off
line = substr(line, iflen+1)
# do argument substitution, if necessary
if (cond && line ~ /\\\$/) {
orig = line
line = ""
for (pos = index(orig, "\\$"); pos > 0; \
pos = index(orig, "\\$")) {
if (pos > 1)
line = line substr(orig, 1, pos-1)
c = substr(orig, pos+2, 1)
if (c ~ /[0-9]/ && c+0 <= nargs)
line = line args[c+0]
orig = substr(orig, pos+3)
}
line = line orig # the remnant
}
# is it an nroff command?
if (cond && line ~ /^\./) {
cmd = substr(line, 1, 3)
while (cmd ~ / $/)
cmd = substr(cmd, 1, length(cmd)-1)
} else
cmd = ""
# deal with it
if (!cond)
nop = 0 # nothing
else if (cmd == "" || macros[cmd] == 0)
print line # not a nested macro
else if (sp >= maxsp)
print ".tm macros nested too deeply (" sp " levels)"
else { # nesting
# stack old one
sp++
nleftstack[sp] = nleft
ptrstack[sp] = ptr
macrostack[sp] = macro
nargstack[sp] = nargs
condstack[sp] = cond
for (i = 1; i <= nargs; i++)
argstack[sp ":" i] = args[i]
# start new one, mostly pulling arguments apart
macro = cmd
nleft = macrolen[macro]
ptr = macros[macro]
cond = 0
argno = 1
pos = length(macro) + 1
for (;;) {
while (substr(line, pos, 1) ~ /[ \t]/)
pos++
if (pos > length(line))
break # NOTE BREAK OUT
arg = ""
if (substr(line, pos, 1) == "\"") {
pos++
while (substr(line, pos, 1) ~ /[^"]/) {
arg = arg substr(line, pos, 1)
pos++
}
pos++
} else
while (substr(line, pos, 1) ~ /[^ \t]/) {
arg = arg substr(line, pos, 1)
pos++
}
args[argno++] = arg
}
nargs = argno - 1
}
# clean up any completed macros
while (nleft <= 0 && sp > 0) {
nleft = nleftstack[sp]
ptr = ptrstack[sp]
macro = macrostack[sp]
nargs = nargstack[sp]
cond = condstack[sp]
for (i = 1; i <= nargs; i++)
args[i] = argstack[sp ":" i]
sp--
}
# finally, get next line
if (nleft > 0) {
line = macrotext[ptr++]
nleft--
} else
line = "" # signal loop to terminate
}
print ".^#", NR - nroffset + 1, inname
next
}
{
# it's ordinary
print
}